home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 10 / The PC-Sig Library - Shareware for the IBM PC and Compatibles (PC-SIG)(Tenth Edition Disks 1-2804)(1991).iso / PC_SIGCD / 05 / 6 / DISK0564.ZIP / SOURCE.ARC / FDUMP.C < prev    next >
C/C++ Source or Header  |  1988-07-09  |  16KB  |  648 lines

  1. /* file dump/patch utility for MSDOS V. 2 or 3 */
  2. /* by Jon Dart, 3012 Hawthorn St., San Diego, CA 92104 */
  3.  
  4. /* This program is PUBLIC DOMAIN.  Enjoy it.  Share it.  Improve it. */
  5.  
  6. /* It compiles under Aztec C version 3.40a. It will probably require
  7.    modification to work with other compilers */
  8.  
  9. #include <ctype.h>
  10. #include <stdio.h>
  11. #include <fcntl.h>
  12. #include <sgtty.h>
  13. #include "ascii.h"
  14. #include "truth.h"
  15. #include "fixpath.h"
  16.  
  17. #define Version "1.7 (04-Oct-86)"
  18. #define SECTSIZE 128  /* physical sector size */
  19. #define LSECTSIZE (long) SECTSIZE /* long version of SECTSIZE */
  20. #define PATHSIZE 65   /* size of a DOS path name plus 1 */
  21. #define MAXSTR 81     /* max. console input line length + 1 */
  22. #define exitch '\004'
  23. #define ShowSector() printf("[%d/%d]",sector,maxsec)
  24. #define offset(sector) (((long) sector) & 0xFFFF)*128L
  25. #define skipsp(s,c) while (((c = *s) == SPACE) || (c==TAB)) s++
  26. #define keyin(c)  c = getc(stdin)
  27.  
  28. extern char *malloc();
  29. extern long lseek();
  30.  
  31. int fd = -1;
  32. unsigned char *buffer;
  33. unsigned int sector,nread,cmdnum,maxsec;
  34. char *FileName;
  35. unsigned char cmdlist[] = "ACDEFHOSWX+-?";
  36. struct sgttyb conopts;
  37.  
  38.  
  39. Menu()
  40.  
  41. /* show menu on screen */
  42.  
  43. {
  44.     printf("\nAvailable commands:\n\n");
  45.  
  46.     printf("--- Dump commands ---       -------- Patch Commands --------\n");
  47.     printf(" A = Dump in ASCII           C = Copy Sector(s) to New File\n");
  48.     printf(" D = Dump in Decimal         E = Edit Sector Buffer\n");
  49.     printf(" H = Dump in Hex             W = Write Buffer to Disk\n");
  50.     printf(" O = Dump in Octal\n");
  51.     printf("\n");
  52.     printf("-- Movement commands --     --- Misc. Commands ---\n");
  53.     printf(" + = Next Sector             F = Select New File\n");
  54.     printf(" - = Previous Sector         ? = Display Commands\n");
  55.     printf(" S = Select Sector           X = Exit to DOS\n");
  56. }
  57.  
  58. WriteShortHeader()
  59.  
  60. {
  61.     printf("    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");
  62.     printf("   ------------------------------------------------\n");
  63. }
  64.  
  65. WriteLongHeader()
  66.  
  67. {
  68.     printf("    0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\n");
  69.     printf("  ----------------------------------------------------------------\n");
  70. }
  71.  
  72. ViewByte(mode,b)
  73. char mode; unsigned char b;
  74. {
  75.     if (mode == 'A') { /* ascii mode */
  76.         b = toascii(b);
  77.         if (isprint(b))
  78.             printf(" %c",b);
  79.         else if (b!='\127') /* non-printing char */
  80.             printf("^%c",b+'A'-1);
  81.         else /* DEL char. */
  82.             printf("^?");
  83.     }
  84.     else if (mode == 'D')
  85.         printf("%3d",b);
  86.     else if (mode == 'H')
  87.         printf("%02x",b);
  88.     else if (mode == 'O')
  89.         printf("%03o",b);
  90. }
  91.  
  92. ViewSector(mode)
  93. char mode;
  94.  
  95. {
  96.     unsigned int i,j,count;
  97.     unsigned char *a;
  98.  
  99.     if (fd != -1) printf("%s ",FileName);
  100.     ShowSector(); putchar(NL);
  101.     if ((mode=='A') || (mode=='H'))
  102.         WriteShortHeader();
  103.     else
  104.         WriteLongHeader();
  105.     count = 0;
  106.     for (i=0;i<8;i++) {
  107.        printf("%1x |",i);
  108.        for (j=0;j<16;j++) {
  109.            if (count<nread) {
  110.                ViewByte(mode,buffer[count]);
  111.                putchar(' ');
  112.                count++;
  113.            }
  114.        }
  115.        putchar(NL);
  116.     }
  117. }
  118.  
  119. GetLine(s,max,exitchar)
  120. char *s; unsigned int max; char exitchar;
  121.  
  122. /* get line from keyboard. max = max # of chars, exitch = char. to cause
  123.    immediate exit.  Returns 0 if exitch typed, 1 if not */
  124.  
  125. {
  126.     unsigned int k,exit;
  127.     char ch;
  128.  
  129.     exit = FALSE;
  130.     k = 0;
  131.     do {
  132.         keyin(ch);
  133.         if (ch == exitchar) {
  134.             ViewByte('A',ch);
  135.             exit = TRUE;
  136.         }
  137.         else if ((ch==BKS) || (ch==DEL)) {
  138.             if (k>0) {
  139.                 --k;
  140.                 putchar(BKS);
  141.                 putchar(SPACE);
  142.                 putchar(BKS);
  143.             }
  144.         }
  145.         else if (ch!=NL) {
  146.             if (k<max) {
  147.                 putchar(ch);
  148.                 s[k] = ch;
  149.                 ++k;
  150.             }
  151.         }
  152.    }
  153.    while ((ch!=NL) && (!exit));
  154.    putchar(NL);
  155.    s[k] = EOS;
  156.    return(!exit);
  157. }
  158.  
  159. GetFile(prompt,filename,mode)
  160. char *prompt; char *filename; int mode;
  161.  
  162. /* get file name from console, open it (in mode) for unbuffered i/o, and
  163.    return filename and file descriptor (as function value) */
  164. /* returns -1 if no file opened */
  165.  
  166. {
  167.     int gotfile, type;
  168.     char sp[PATHSIZE],lip[PATHSIZE];
  169.     char c;
  170.     long int filelen;
  171.     int fd;
  172.  
  173.     gotfile = FALSE;
  174.     fd = -1;
  175.     do {
  176.         printf("%s",prompt);
  177.         if (!GetLine(filename,PATHSIZE,exitch)) return;
  178.         skipsp(filename,c);
  179.         if (c!=EOS) {
  180.             fd = open(filename,mode);
  181.             if (fd == -1) printf("\nCan't open: %s\n",filename);
  182.         }
  183.    } while ((filename[0]!=EOS) && (fd == -1));
  184.    return(fd);
  185. }
  186.  
  187. NewFile()
  188.  
  189. /* open new file for viewing/patching */
  190. /* returns its file descriptor (-1 if no file opened) */
  191.  
  192. {
  193.     long filelen;
  194.     int fd;
  195.  
  196.     fd = GetFile("File name? ",FileName,O_RDWR);
  197.     if (fd != -1) {
  198.         nread = read(fd,buffer,SECTSIZE);
  199.         filelen = lseek(fd,0L,2);
  200.         maxsec = (filelen/((long) SECTSIZE)) & 0xFFFF;
  201.         lseek(fd,0L,0);
  202.     }
  203.     sector = 0;
  204.     return(fd);
  205. }
  206.  
  207. CmdSrc(s,ch)
  208. register char *s; char ch;
  209.  
  210. /* look for ch in s, return index to 1st match (1..length(s)) or 0 if
  211.    not found */
  212.  
  213. {
  214.     int j;
  215.     j = 1;
  216.     while (*s) {
  217.         if (*s==ch)
  218.             return(j);
  219.         else {
  220.             j++;
  221.             s++;
  222.         }
  223.     }
  224.     return(0);
  225. }
  226.  
  227. StringToNum(d,base,num)
  228. char *d; unsigned int base; int *num;
  229.  
  230. /* converts number in string d (of given base) to integer num */
  231. /* returns 0 if error */
  232.  
  233. {
  234.      int n;
  235.  
  236.      switch(base) {
  237.      case 10: n = sscanf(d,"%d",num); break;
  238.      case 16: n = sscanf(d,"%x",num); break;
  239.      case 8:  n = sscanf(d,"%o",num); break;
  240.      default:
  241.          return(0);
  242.      }
  243.      if (n==1)
  244.          return(1);
  245.      else
  246.          return(0);
  247. }
  248.  
  249. CheckDigit(mode,ch)
  250. /* returns !=0 if ch is legal input for mode */
  251. char mode,ch;
  252. {
  253.     if (mode=='D') 
  254.          return(isdigit(ch));
  255.     else if (mode=='O')
  256.          return((ch>='0') && (ch<='7'));
  257.     else if (mode=='H') {
  258.          if (!isascii(ch))
  259.              return(0);
  260.          else {
  261.              ch = toupper(ch);
  262.              return(isdigit(ch) || ((ch>='A') && (ch<='F')));
  263.        }
  264.     }
  265.     else /* ascii mode, anything goes */
  266.         return(1);
  267. }
  268.  
  269. stuff(s,mode,base,buffer,i)
  270. register char *s; char mode; int base; unsigned char *buffer; int i;
  271.  
  272. /* read bytes from s, stuff into buffer at position i, return new value of i */
  273.  
  274. {
  275.     int j,k,done,num;
  276.     char d[MAXSTR];
  277.     register char ch;
  278.  
  279.     j = 0; done = TRUE;
  280.     if (mode=='A') { /* ascii mode */
  281.         k = 0;
  282.         while (s[j]!='\0') {
  283.             k = (i+j) & (SECTSIZE-1);
  284.             buffer[k] = s[j];
  285.             j++;
  286.         }
  287.         i = (k+1) & (SECTSIZE-1);
  288.     }
  289.     else
  290.     do {
  291.         skipsp(s,ch);
  292.         k = 0; 
  293.         /* see if data string ok */
  294.         while ( CheckDigit(mode,ch) ) {
  295.             d[k++] = ch;
  296.             ch = *s++;
  297.         }
  298.         if ((ch!='\0') && !isspace(ch)) { /* non-numeric char. */
  299.             printf("Bad character in input: %c\n",ch);
  300.             return(i);
  301.         }
  302.         d[k]=EOS;
  303.         if (k==0) /* nothing typed, just advance to next byte */
  304.             i = (i+1) & (SECTSIZE-1);
  305.         else { /* got a number in d */
  306.             if (StringToNum(d,base,&num)) {
  307.                 buffer[i] = num;
  308.                 i = (i + 1) & (SECTSIZE-1);
  309.             }
  310.             else { /* conversion error */
  311.                 printf("Error in value: %s\n",d);
  312.                 done = FALSE;
  313.             }
  314.         }
  315.     } while ((done) && (ch!=EOS));
  316.     return(i);
  317. }
  318.  
  319. EditSector(mode,start)
  320. char mode; unsigned int start;
  321.  
  322. /* accept patch info from user and modify the buffer.  'mode' is
  323.    'D', 'H' or 'O' (for decimal, hex, octal).  'start' is the
  324.    index into the buffer for the first byte to be patched. */
  325.  
  326. {
  327.  
  328.     unsigned int base,i,j,k,num,exit;
  329.     char s[MAXSTR],c,ch;
  330.     unsigned char *a;
  331.  
  332.     switch(mode) {
  333.        case 'D': base = 10; break;
  334.        case 'H': base = 16; break;
  335.        case 'O': base = 8;  break;
  336.        default:
  337.        /* base undefined */ ;
  338.     }
  339.     i = start; exit = FALSE;
  340.     do {
  341.         printf("%02x: ",i);
  342.         a = buffer + i;
  343.         ViewByte(mode,*a); printf(" -> ");
  344.         if ((exit = !GetLine(s,MAXSTR,exitch))==FALSE)
  345.             i = stuff(s,mode,base,buffer,i);
  346.     }
  347.     while (exit==FALSE);
  348. }
  349.  
  350. MoveToSec(newsec)
  351. unsigned int newsec;
  352.  
  353. /* seeks to a new sector, reads it into buffer, and sets global vars.
  354.    appropriately.  Returns 0 if error */
  355.  
  356. {
  357.     if (newsec>maxsec) newsec=maxsec;
  358.     lseek(fd,offset(newsec),0);  /* rewind to start of file */
  359.     nread = read(fd,buffer,SECTSIZE);
  360.     lseek(fd,offset(newsec),0);
  361.     if (nread == -1) {
  362.         printf("\nDisk read error.\n");
  363.         MoveToSec(sector); /* attempt to return to old sector */
  364.         return(0);
  365.     }
  366.     else {
  367.         sector=newsec;
  368.         return(1);
  369.     }
  370. }
  371.  
  372. GetSecRange(sec1,sec2)
  373. register int *sec1,*sec2;
  374.  
  375. /* get a single sector number or a range of sector numbers from the
  376.    console. returns 0 if error */
  377.  
  378. {
  379.     char d[20],sectnums[20];
  380.     char *ds,*s;
  381.     char c;
  382.     int err;
  383.  
  384.     do {
  385.         err = FALSE;
  386.         printf("Copy which sectors (0-%d)? ",maxsec);
  387.         if (!GetLine(sectnums,20,exitch))
  388.             return(0);
  389.         s = sectnums; ds = d;
  390.         skipsp(s,c);
  391.         if (c==EOS)
  392.             return(0);
  393.         while (isdigit(*s)) *ds++ = *s++;
  394.         *ds = EOS;
  395.         err = (sscanf(d,"%d",sec1) == 1) ? FALSE : TRUE;
  396.         if (!err && (*s==EOS)) { /* only 1 num specified */
  397.             *sec2 = *sec1;
  398.         }
  399.         if (!err && (*s=='-')) {
  400.             ds = d;
  401.             while (isdigit(*(++s))) *ds++ = *s;
  402.             *ds = EOS;
  403.             if (sscanf(d,"%d",sec2)!=1)
  404.                 err = TRUE;
  405.         }
  406.         if (err || (*sec1<0) || (*sec1>maxsec) || (*sec2<0) || (*sec2>maxsec)) {
  407.            printf("\nEnter a single sector or a range of sectors (0-%d).\n",maxsec);
  408.         }
  409.     } while (err);
  410.     return(!err);
  411. }
  412.  
  413. CopySectors()
  414.  
  415. /* copy sector(s) from currently open file to another file */
  416.  
  417. {
  418.     int fd2,sec1,sec2,nr,nw,i;
  419.     char fn2[PATHSIZE];
  420.     char c;
  421.     char sectnums[20];
  422.     char secbuf[SECTSIZE];
  423.     char d[5];
  424.     char *s,*ds;
  425.  
  426.     if (fd == -1) {
  427.         printf("\nNo file open.\n");
  428.         return;
  429.     }
  430.     if ((fd2 = GetFile("File name to copy to? ",fn2,O_CREAT+O_WRONLY)) == -1)
  431.         return;
  432.     if (!GetSecRange(&sec1,&sec2)) {
  433.         close(fd2);
  434.         return;
  435.     }
  436.     lseek(fd,offset(sec1),0);
  437.     for (i=sec1;i<=sec2;i++) {
  438.         nr = read(fd,secbuf,SECTSIZE);
  439.         nw = write(fd2,secbuf,nr);
  440.     }
  441.     close(fd2);
  442.     MoveToSec(sector);
  443. }
  444.  
  445. Change()
  446.  
  447. /* change contents of sector buffer */
  448.  
  449. {
  450.     char s[5];
  451.     unsigned int num,base,done,exit,ok;
  452.     static char options[] = "ADHO";
  453.     char mode;
  454.  
  455.     printf("Format (A = Ascii, D = Decimal, H = Hex, O = Octal)? ");
  456.     do {
  457.         keyin(mode);
  458.         mode = toupper(mode);
  459.     }
  460.     while ((CmdSrc(options,mode) == 0) && (mode!=NL));
  461.     putchar(mode);
  462.     if (mode != NL) {
  463.         ok = FALSE;
  464.         do {
  465.             printf("\nStarting address within buffer (00-7F)? ");
  466.             if (!GetLine(s,MAXSTR,exitch)) return;
  467.             if (StringToNum(s,16,&num)) {
  468.                 ok = TRUE;
  469.                 if (mode=='A') {
  470.                     printf("Enter text to replace existing sector contents.\n");
  471.                     printf("Type ^D when done.\n");
  472.                 }
  473.                 else {
  474.                     printf("Enter new bytes, one or more per line.\n");
  475.                     printf("Use spaces to separate. Type ^D when done.\n");
  476.                 }
  477.                 EditSector(mode,num);
  478.             }
  479.         } while (!ok);
  480.     }
  481. }
  482.  
  483. Forward()
  484.  
  485. {
  486.     if (sector+1<=maxsec) {
  487.         if (MoveToSec(sector+1)) {
  488.             ShowSector();
  489.             putchar(NL);
  490.         }
  491.     }
  492.     else
  493.         printf("[END OF FILE]");
  494. }
  495.  
  496. Reverse()
  497.  
  498. {
  499.     if (sector > 0) {
  500.        if (MoveToSec(sector-1)) {
  501.        /* read ok */
  502.            ShowSector(); putchar(NL);
  503.        }
  504.     }
  505. }
  506.  
  507. SetSector()
  508.  
  509. {
  510.     int newsec;
  511.     char s[MAXSTR];
  512.  
  513.     if (maxsec>0) {
  514.         printf("Sector (0-%d)? ",maxsec);
  515.         if (GetLine(s,MAXSTR,exitch)) {
  516.             if (StringToNum(s,10,&newsec)) {
  517.                 if (MoveToSec(newsec)) {
  518.                     ShowSector();
  519.                     putchar(NL);
  520.                 }
  521.             }
  522.             else
  523.                 printf("\nError - bad number\n");
  524.         }
  525.     }
  526. }
  527.  
  528. Update()
  529.  
  530. {
  531.     int nwritten;
  532.  
  533.     lseek(fd,offset(sector),0);
  534.     nwritten = write(fd,buffer,SECTSIZE);
  535.     lseek(fd,offset(sector),0);
  536.     if (nwritten != SECTSIZE) {
  537.        printf("\nError (probably disk full)\n");
  538.     }
  539. }
  540.  
  541. DoCommand(cmd)
  542. char cmd;
  543. {
  544.     putchar(cmd);
  545.     putchar(NL);
  546.     switch(cmd) {
  547.     case 'E': Change();    break;
  548.     case 'C': CopySectors(); break;
  549.     case 'A':
  550.     case 'D':
  551.     case 'H':
  552.     case 'O': ViewSector(cmd); break;
  553.     case 'S': SetSector();      break;
  554.     case 'F': {
  555.                if (fd != -1) close(fd);
  556.                fd = NewFile(); break;
  557.               }
  558.     case 'W': Update();    break;
  559.     case '+': Forward();   break;
  560.     case '-': Reverse();   break;
  561.     case '?': Menu();      break;
  562.     default:
  563.           /* nothing */ ;
  564.     }
  565. }
  566.  
  567. main(argc,argv)
  568. int argc; char *argv[];
  569. {
  570.     struct regstruc {
  571.        unsigned int ax,bx,cx,dx,si,di;
  572.     } inregs, outregs;
  573.     unsigned int ctlcstat;
  574.     int gotfile;
  575.     long filelen;
  576.     char cmd;
  577.  
  578.     printf("File Dump/Patch Utility\n");
  579.     printf("by Jon Dart ...  Version %s\n\n",Version);
  580.  
  581.     /* turn on char. mode, no echo */
  582. #ifndef DEBUG
  583.     ioctl(fileno(stdin),TIOCGETP,&conopts);
  584.     conopts.sg_flags |= (CBREAK+CRMOD);
  585.     conopts.sg_flags &= ~(ECHO);
  586.     ioctl(fileno(stdin),TIOCSETP,&conopts);
  587. #endif
  588.     inregs.ax = 0;
  589.     doscall(0x33,&inregs,&outregs);  /* get current ^C status */
  590.     ctlcstat = outregs.dx; /* save it */
  591.     inregs.ax = 1;
  592.     inregs.dx = 0;
  593.     doscall(0x33,&inregs,&outregs); /* turn off ^C trapping */
  594.  
  595.     buffer = (unsigned char *)  malloc(SECTSIZE);
  596.     FileName = malloc(PATHSIZE);
  597.     gotfile = FALSE;
  598.  
  599.     if (argc>1) {
  600.         fd = open(argv[1],O_RDWR);
  601.         gotfile = (fd != -1);
  602.         if (!gotfile) {
  603.             printf("\nError - can't open: %s\n",argv[1]);
  604.         }
  605.         else {
  606.             nread = read(fd,buffer,SECTSIZE);
  607.             filelen = lseek(fd,0L,2);
  608.             maxsec = (filelen/((long) SECTSIZE)) & 0xFFFF;
  609.             lseek(fd,0L,0);
  610.             sector = 0;
  611.             strcpy(FileName,argv[1]);
  612.             printf("File %s\n",FileName);
  613.         }
  614.     }
  615.     if (gotfile || (fd = NewFile()) != -1) { /* file open ok */
  616.         Menu(); printf("\n->");
  617.         do {
  618.             clrco(); /* clear type-ahead */
  619.             keyin(cmd);
  620.             cmd = toupper(cmd);
  621.             cmdnum = CmdSrc(cmdlist,cmd);
  622.             if (cmdnum) { /* valid command, execute it */
  623.                 DoCommand(cmd);
  624.                 if (cmd != 'X') {
  625.                     printf("\n->");
  626.                 }
  627.             }
  628.         }
  629.         while (cmd!='X');
  630.     }
  631.     if (fd != -1) close(fd);
  632.     free(buffer);
  633.  
  634.     /* restore console to line mode, with echo: */
  635.  
  636.     ioctl(fileno(stdin),TIOCGETP,&conopts);
  637.     conopts.sg_flags &= ~(CBREAK+CRMOD);
  638.     conopts.sg_flags |= ECHO;
  639.     ioctl(fileno(stdin),TIOCSETP,&conopts);
  640.  
  641.     /* restore old ^C status */
  642.  
  643.     inregs.ax = 1;
  644.     inregs.dx = ctlcstat;
  645.     doscall(0x33,&inregs,&outregs);
  646. }
  647.  
  648.